/**
 * MousepadTouchListener.java
 *
 * Created by Andrew Moss on 16 May 2011
 *
 * Contains a class for handling touch events on the Mousepad.
 */

package com.mossdev.android.moteapp.listeners;

import com.mossdev.android.moteapp.Config;
import com.mossdev.android.moteapp.MoteApp;
import com.mossdev.android.moteapp.comms.Commands;
import com.mossdev.android.moteapp.comms.ServerConnectionException;

import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

/**
 * A class for dealing with the users touch events on the mousepad.
 * It will interpret the user's input as movement in along the x and y
 * axes in the Server's XSession. Currently assumes one pointer.
 * Multitouch is not supported.
 * 
 * Originally based on the TouchpadListener class.
 * 
 * @author Andrew Moss
 */
public class MousepadTouchListener implements OnTouchListener {

	//Constants
	//------------------------
	
	private static final long MAX_TAP_LENGTH = 250; //Max length of a tap
	
	
	//Globals
	//------------------------
	
	private boolean movement = false; //record whether any movement seen
	private float move_mag = 0f;
	
	//Previous coords of a pointer during touch events
	private float lastX = 0f;
	private float lastY = 0f;
	
	
	//Methods
	//------------------------

	@Override
	/**
	 * Called when touch event occurs on view this is used as a listener for.
	 */
	public boolean onTouch(View v, MotionEvent event) {
		
		float currentX = 0f;
		float currentY = 0f;

		// Get the type of action driving the callback
		switch (event.getAction()) {
		
		//Second pointer put down, first must have been for click and drag gesture
		case (MotionEvent.ACTION_POINTER_DOWN):
		case (MotionEvent.ACTION_DOWN): {
			// reset movement indicator
			this.movement = false;
			this.move_mag = 0f;
			
			//Record the coords for movement events
			this.lastX = event.getX();
			this.lastY = event.getY();

			break;
		}
		
		// end of click and drag
		case (MotionEvent.ACTION_POINTER_UP):
		case (MotionEvent.ACTION_UP): {
			// if no movement since down event
			if (!this.movement) {
				// if time since down event not too long
				if ((event.getDownTime() + MAX_TAP_LENGTH) > event.getEventTime()) {
					// tap event
					Log.e(Config.LogTag, "Tap");
					try {
						MoteApp.servercomms.sendCommand(Commands.MOUSE_CLICK_L);
					} catch (ServerConnectionException e) {
						Log.e(Config.LogTag, e.err_msg);
					}

				}
			}
			break;
		}
		
		case (MotionEvent.ACTION_MOVE): {

			currentX = event.getX();
			currentY = event.getY();

			//Ignore out of view touches
			if (currentX < 0 || currentY < 0) break;
			
			// Get Magnitude of movement in x and y
			float mag_y = currentY - this.lastY;
			float sane_mag_y = mag_y;
			if (mag_y < 0) sane_mag_y = mag_y *-1;
			
			float mag_x = currentX - this.lastX;
			float sane_mag_x = mag_x;
			if (mag_x < 0) sane_mag_x = mag_x *-1;
			
			// log the movement
			this.move_mag += sane_mag_y + sane_mag_x;
			if (this.move_mag > 10) //arbitrary value to allow some movement with a tap
				this.movement = true;
			
			//Movement command
			try {
				MoteApp.servercomms.sendCommand(Commands.PREFIX_MOUSE_M + new Integer(Math.round(mag_x)).toString() + " " + new Integer(Math.round(mag_y)).toString());
			} catch (ServerConnectionException e) {
				Log.e(Config.LogTag, e.err_msg);
			}
			
			//Record the coords for movement events
			this.lastX = currentX;
			this.lastY = currentY;
			
			break;
		}
		
		default: {
			//do nothing
			break;
		}
		}
		
		return true;
	}

}
